home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-10-13 | 31.9 KB | 1,122 lines |
- This file contains 3 files:
- xmem.h : c include file
- xmem.asm : low level basic XMS acess
- xmemc.c : super easy C access via functions like fopen, fread, fwrite
- xopen, xread, xwrite, xseek etc...
-
- FOR DOS REAL mode programs, requires HIMEM.SYS to be loaded in
- config.sys.
-
- XMEM.H ------------- START --------------------------------------------------
- #if !defined(_XMEM_H)
- #define _XMEM_H
-
- typedef struct xms_node
- {
- long start, size, off;
- short used;
- struct xms_node *next;
- }
- xms_node_t;
-
- typedef struct
- {
- int handle;
- unsigned long total;
- unsigned long avail;
- unsigned long next_off;
- xms_node_t *next;
- }
- xms_head_t;
-
- #define XMSBLOCK 16384u
- #define XMSBLOCKSHIFT 14
-
- extern void LSHL( unsigned long far *SHLnumber, unsigned short n );
-
- extern unsigned short XMS_available( void );
-
- extern unsigned short XMSblk_available( void );
-
- extern short XMS_alloc(unsigned short rsrvd,
- unsigned short far *size
- );
- extern short XMS_dealloc(unsigned short Hdl );
- extern short XMStoMem(unsigned short Handle, // XMS handle returned by XMS_alloc()
- unsigned short blk, // which 16k block to copy to
- unsigned short blkAdr, // offset within 16k block
- unsigned short Bytes, // bytes to copy
- void far *memAdr
- );
- extern short MemToXMS(unsigned short Handle,
- unsigned short blk,
- unsigned short blkAdr,
- unsigned short Bytes,
- void far *memAdr
- );
-
- // call these for ease
- short alloc_xms(unsigned short far *size); // size in 16k blocks
- // NOTE size is changed to the amount block size was altered by!
- // normaly this is zero
-
- short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n);
- short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n);
- void deinit_xms(void);
- short init_xms(unsigned short min_blocks);
- void qfree_xms(xms_node_t *node);
- xms_node_t *qalloc_xms(unsigned long size);
- xms_node_t *xms_open(char *file);
- short xms_read(void far *buffer, unsigned short n, xms_node_t *node);
- short xms_write(void far *buffer, unsigned short n, xms_node_t *node);
- long xms_tell(xms_node_t *node);
- short xms_seek(xms_node_t *node, long off, short whence);
- void xms_close(xms_node_t *node);
-
- extern xms_head_t xms_head;
-
- #endif
- /* ---------------------------------- end of file --------------------- */
-
- XMEM.H ------------- END --------------------------------------------------
-
- xmem.asm --------------------- START --------------------------------------
- ;-----------------------------------------------------------------------
- ;
- .MODEL MEDIUM
-
- EXTmemError EQU 7
- XMSmemError EQU 8
-
-
- ShortAdr EQU 0
- LongAdr EQU 1
-
- procname MACRO Pnam
- PUBLIC _&Pnam&
- _&Pnam& PROC FAR
- ENDM
-
- endproc MACRO Pnam
-
- _&Pnam& ENDP
-
- ENDM
-
- pwrlolvl_TEXT SEGMENT WORD PUBLIC 'CODE'
-
- ASSUME CS:pwrlolvl_TEXT, DS:pwrlolvl_TEXT, ES:pwrlolvl_TEXT
-
- SUBTTL (Local Procedure) XMS_setup - find a XMS driver.
- PAGE+
-
- EVEN
- XMSwordByte LABEL BYTE
- XMSword DW 0
-
- XMSmoveSTRUC STRUC
-
- Length DW 0
- LengthX DW 0
- SrcHandle DW 0
- SrcOffset DW 0
- SrcOffsetX DW 0
- DestHandle DW 0
- DestOffset DW 0
- DestOffsetX DW 0
-
- XMSmoveSTRUC ENDS
-
- XMSmainGET XMSmoveSTRUC <>
- XMSmainPUT XMSmoveSTRUC <>
- XMSwordGET XMSmoveSTRUC <2,,,,,,OFFSET XMSword>
- XMSwordPUT XMSmoveSTRUC <2,,,OFFSET XMSword>
-
- XMSfunctAdr DW 0, 0
-
- ; Don't try to call this from your programs
-
- XMS_setup PROC NEAR
-
- PUSH DS
- PUSH ES
- PUSH BX
-
- MOV AX,CS ; Set Data segment to the code segment.
- MOV DS,AX ;
- MOV [XMSwordGET.DestOffsetX],AX ; Set up the move data structures.
- MOV [XMSwordPUT.SrcOffsetX],AX ;
-
- MOV AX,4300H ; See if a XMS Driver Exists.
- INT 2FH ;
- CMP AL,80H ;
- MOV AX,0 ;
- JNE XMS_setup01 ; Return 0 if not.
-
- MOV AX,4310H ; If so, set the driver's function
- INT 2FH ; address.
- MOV [XMSfunctAdr],BX ;
- MOV [XMSfunctAdr+2],ES ;
-
- MOV AX,1 ; Return 1.
-
- XMS_setup01:
- POP BX
- POP ES
- POP DS
-
- RET
-
- XMS_setup ENDP
-
- SUBTTL LSHL - Shift an unsigned long left
- PAGE+
-
- ;****************************************************************************
- ;*
- ;* Shift an unsigned long integer left n number of bits.
- ;*
- ;****************************************************************************
-
- ;
- ; Stack frame definition for void LSHL( unsigned long *SHLnumber, unsigned n );
- ;
-
- LSHLparms STRUC
-
- DW 0, 0
- DW 0
- SHLadr DD ?
- SHLn DW ?
-
- LSHLparms ENDS
-
- procname LSHL
-
- PUSH BP
- MOV BP,SP
-
- PUSH BX
- PUSH CX
- PUSH DX
-
- PUSH DS
- LDS BX,SHLadr[BP]
- MOV CX,SHLn[BP]
-
- MOV AX,[BX] ; Get the long integer.
- MOV DX,[BX+2] ;
-
- LSHL_01:
- SHL AX,1 ; Do the long shift.
- RCL DX,1 ;
- LOOP LSHL_01 ;
-
- MOV [BX],AX ; Replace the addressed number.
- MOV [BX+2],DX ;
-
- POP DS
- POP DX
- POP CX
- POP BX
-
- POP BP
- RET ; Exit
-
- endproc LSHL
-
-
- SUBTTL Extended Memory - Stack template for EXTget, EXTput
- PAGE+
-
- EXTgpparms STRUC
-
- DW 0, 0
- DW 0
- extgpBase DW ?
- extgpblk DW ?
- extgpblkAdr DW ?
- extgpBytes DW ?
- extgpmemAdr DW ?
- DW ?
-
- EXTgpparms ENDS
-
-
-
- SUBTTL Extended Memory - XMS - Return total XMS memory.
- PAGE+
-
- ; Use this function to detect wether or not XMS driver installed
- ;
- ; Stack frame definition for unsigned XMS_available( void );
- ;
- ; The total XMS memory available (in 16k blocks) is returned.
- ;
- procname XMS_available
-
- PUSH BX
- PUSH CX
- PUSH DX
-
- CALL XMS_setup ; Ensure XMS memory is set.
- TEST AX,AX ;
- JZ XMS_available01 ; Return zero if not.
-
- MOV AH,08H ; Set the size function code.
- CALL DWORD PTR CS:[XMSfunctAdr] ; Get the size.
- TEST AX,AX ;
- JZ XMS_available01 ;
-
- MOV AX,DX ; Set available Kbytes.
- SUB AX,64 ; Subtract out the HMA (HIMEM.SYS bug).
- JNC XMS_available01 ;
- XOR AX,AX ; Set zero if underflow.
-
- XMS_available01:
- MOV CL,4 ; Divide Kbytes by 16 for blocks.
- SHR AX,CL ;
-
- POP DX
- POP CX
- POP BX
-
- RET ; Exit
-
- endproc XMS_available
-
- SUBTTL Extended Memory - XMS - Return largest block XMS mem.
- PAGE+
-
- ;
- ; Stack frame definition for unsigned XMSblk_available( void );
- ;
- ; The size of the largest block of XMS memory available,
- ; (in 16Kbyte blocks) is returned.
- ;
- procname XMSblk_available
-
- PUSH BX
- PUSH CX
- PUSH DX
-
- CALL XMS_setup ; Ensure XMS memory is set.
- TEST AX,AX ;
- JZ XMSblk_available01 ; Return zero if not.
-
- MOV AH,08H ; Set the size function code.
- CALL DWORD PTR CS:[XMSfunctAdr] ; Get the size.
- TEST AX,AX ;
- JZ XMSblk_available01 ;
-
- SUB DX,64 ; Subtract out the HMA (HIMEM.SYS bug).
- JNC XMSblk_available0X ;
- XOR DX,DX ; Set zero if underflow.
-
- XMSblk_available0X:
- CMP AX,DX ;
- JBE XMSblk_available01 ;
- MOV AX,DX ; Set available Kbytes.
-
- XMSblk_available01:
- MOV CL,4 ; Divide Kbytes by 16 for blocks.
- SHR AX,CL ;
-
- POP DX
- POP CX
- POP BX
-
- RET ; Exit
-
- endproc XMSblk_available
-
- SUBTTL Extended Memory - XMS De-allocate a memory block.
- PAGE+
-
- ;
- ; Stack frame definition for int XMS_dealloc( int Hdl );
- ;
- ; Zero is returned if the operation fails, non-zero if success.
- ;
- ; its really important to do this, only other way to recover
- ; XMS blocks is to re-boot
-
- XMSdealparms STRUC
-
- DW 0, 0
- DW 0
- xmsdealHdl DW ?
-
- XMSdealparms ENDS
-
-
- procname XMS_dealloc
-
- PUSH BP
- MOV BP,SP
-
- PUSH BX
- PUSH DX
-
- ; CALL XMS_setup ; Ensure XMS memory is set.
- ; TEST AX,AX ;
- ; JZ XMS_dealloc01 ; Return zero if not.
-
- MOV DX,xmsdealHdl[BP] ; Get the handle to de-allocate.
- MOV AH,0AH ;
-
- CALL DWORD PTR CS:[XMSfunctAdr] ; De-allocate it.
-
- XMS_dealloc01:
- POP DX
- POP BX
-
- POP BP
- RET ; Exit
-
- endproc XMS_dealloc
-
- SUBTTL Extended Memory - XMS Allocate a memory block.
- PAGE+
-
- ;
- ; Stack frame definition for int XMS_alloc( unsigned rsrvd, *size );
- ;
- ; rsrved and size are in 16K byte blocks.
- ; rsrved is mem set aside for EMS, generaly zero
- ;
- ; Zero is returned if the operation fails.
- ; Block (XMS) handle is returned if success.
- ;
- ; size - is reduced by the amount of XMS memory actually allocated.
- ;
-
- XMSalparms STRUC
-
- DW 0, 0
- DW 0
- xmsalrsrvd DW ?
- xmsalsize DD ?
-
- XMSalparms ENDS
-
- procname XMS_alloc
-
- PUSH BP
- MOV BP,SP
-
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH ES
- PUSH DS
-
- MOV AX,CS ; Set the data segment to the code
- MOV DS,AX ; segment.
-
- MOV CX,4 ;
- ADD xmsalrsrvd[BP],CX ; Subtract out the HMA (HIMEM.SYS bug).
- SHL xmsalrsrvd[BP],CL ; Convert reserved blocks to K-bytes.
-
- LES DI,xmsalsize[BP] ; Load size address.
- XOR AX,AX ;
- MOV BX,ES:[DI] ; Get the requested size in blocks.
-
- TEST BX,0F000H ; Check for more than 64 Megabytes.
- JZ XMS_alloc01 ;
- MOV BX,00FFFH ;
-
- XMS_alloc01:
- MOV CL,4 ;
- SHL BX,CL ; Convert to K-Bytes.
- MOV CX,BX ; In CX.
- JZ XMS_alloc05 ; Return zero if no size requested.
-
- ; CALL XMS_setup ; Ensure XMS memory is set.
- ; TEST AX,AX ;
- ; JZ XMS_alloc05 ; Return zero if not.
-
- XOR BX,BX ;
- MOV AH,08H ; Set to Query Free XMS Memory.
- CALL DWORD PTR [XMSfunctAdr] ;
-
- SUB DX,xmsalrsrvd[BP] ; Subtract out reserved blocks.
- JB XMS_alloc03 ; Ensure no borrow.
- CMP AX,DX ;
- JBE XMS_alloc02 ;
- MOV AX,DX ;
-
- XMS_alloc02:
- MOV DX,AX ;
- CMP AX,68 ; Ensure enough memory to allocate.
-
- XMS_alloc03:
- MOV AX,0 ;
- JB XMS_alloc05 ; Exit if not.
-
- CMP BL,80H ; Check for errors.
- JE XMS_alloc05 ;
- CMP BL,81H ;
- JE XMS_alloc05 ;
-
- CMP CX,DX ; Check actual against requested size.
- JBE XMS_alloc04 ;
- MOV CX,DX ; Set if actual < requested.
-
- XMS_alloc04:
- MOV DX,CX ; Set requested size.
- MOV AH,09H ;
- CALL DWORD PTR [XMSfunctAdr] ; Allocate it.
- DEC AX ; Check for errors.
- MOV AX,0 ;
- JNZ XMS_alloc05 ;
-
-
- MOV AX,CX ; Convert allocated size in KBytes
- MOV CL,4 ; to allocated blocks.
- SHR AX,CL ;
-
- SUB ES:[DI],AX ; Subtract the blocks allocated.
- MOV AX,DX ; Set to return the handle.
-
- XMS_alloc05:
- POP DS
- POP ES
- POP DI
- POP DX
- POP CX
- POP BX
-
- POP BP
- RET ; Exit
-
- endproc XMS_alloc
-
- SUBTTL Extended Memory - XMS get, put Stack Frame definition
- PAGE+
-
-
- XMSgpparms STRUC
-
- DW 0, 0
- DW 0
- xmsgpHdl DW ?
- xmsgpblk DW ?
- xmsgpblkAdr DW ?
- xmsgpBytes DW ?
- xmsgpmemAdr DD ?
-
- XMSgpparms ENDS
-
- SUBTTL Extended Memory - XMStoMem
- PAGE+
-
-
- ;
- ; Stack frame definition for int XMStoMem( unsigned Handle,
- ; unsigned blk,
- ; unsigned blkAdr,
- ; unsigned Bytes,
- ; char *memAdr
- ; );
- ;
- ; XMSmemError is returned if the operation fails, Zero if success.
- ;
-
- procname XMStoMem
-
- PUSH BP
- MOV BP,SP
-
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH ES
- PUSH DS
-
- MOV AX,CS ; Set Data Segment to Code Segment.
- MOV DS,AX ;
-
- MOV CX,xmsgpBytes[BP] ; Get the number of bytes to transfer.
- LES BX,xmsgpmemAdr[BP] ; Get the memory address.
- MOV DX,xmsgpHdl[BP] ; Get the XMS handle.
- MOV [XMSmainGET.SrcHandle],DX ; Set it in the move structures.
- MOV [XMSwordGET.SrcHandle],DX ;
-
- XOR DX,DX ;
- MOV DI,xmsgpblk[BP] ; Get the block number.
- SHR DI,1 ; Form the 32 bit XMS address in
- RCR DX,1 ; DI:DX.
- SHR DI,1 ;
- RCR DX,1 ;
- ADD DX,xmsgpblkAdr[BP] ;
-
- TEST CX,1 ; Check for an odd number of bytes
- JZ XMStoMem02 ; to transfer.
-
- DEC CX ; Decrement to an even number of bytes.
-
- TEST DX,1 ; Check for an odd XMS address.
- JZ XMStoMem01 ;
-
- ; XMS address is odd.
- ; -------------------
- DEC DX ;
- MOV [XMSwordGET.SrcOffset],DX ; Set the XMS address.
- MOV [XMSwordGET.SrcOffsetX],DI ;
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSwordGET ; Set address of the move structure.
-
- PUSH BX ;
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- POP BX ;
- DEC AX ; Check for errors.
- JNZ XMStoMem03 ; Error out if error.
-
- MOV AX,[XMSword] ; Get the moved word.
-
- MOV ES:[BX],AH ; Move the odd byte to memory.
-
- INC BX ; Reset the memory address.
- ADD DX,2 ; And the XMS address.
-
- JMP XMStoMem02 ; Move the block.
-
-
- XMStoMem01:
- ; XMS address is even.
- ; --------------------
- ADD DX,CX ;
- MOV [XMSwordGET.SrcOffset],DX ; Set the XMS address.
- SUB DX,CX ;
- MOV [XMSwordGET.SrcOffsetX],DI ;
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSwordGET ; Set address of the move structure.
-
- PUSH BX ;
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- POP BX ;
- DEC AX ; Check for errors.
- JNZ XMStoMem03 ; Error out if error.
-
- MOV AX,[XMSword] ; Get the moved word.
-
- XCHG DI,CX ;
- MOV ES:[BX+DI],AL ; Move the odd byte to memory.
- XCHG DI,CX ;
-
- XMStoMem02:
- JCXZ XMStoMem04 ; Avoid a zero byte move.
-
- MOV XMSmainGET.Length,CX ; Set length for the move.
-
- MOV XMSmainGET.DestOffset,BX ; Set Memory address.
- MOV XMSmainGET.DestOffsetX,ES ;
-
- MOV XMSmainGET.SrcOffset,DX ; Set XMS address.
- MOV XMSmainGET.SrcOffsetX,DI ;
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSmainGET ; Set address of the move structure.
-
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- DEC AX ; Check for errors.
- JZ XMStoMem05
-
- XMStoMem03:
- MOV AX,XMSmemError ; Set error code if error.
- JMP XMStoMem05 ;
-
- XMStoMem04:
- XOR AX,AX ;
-
- XMStoMem05:
- POP DS
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
-
- POP BP
- RET ; Exit
-
- endproc XMStoMem
-
- SUBTTL Extended Memory - MemToXMS
- PAGE+
-
-
- ;
- ; Stack frame definition for int MemToXMS( unsigned Handle,
- ; unsigned blk,
- ; unsigned blkAdr,
- ; unsigned Bytes,
- ; char *memAdr
- ; );
- ;
- ; XMSmemError is returned if the operation fails, Zero if success.
- ;
-
- procname MemToXMS
-
- PUSH BP
- MOV BP,SP
-
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH ES
- PUSH DS
-
- MOV AX,CS ;
- MOV DS,AX ;
-
- MOV CX,xmsgpBytes[BP] ; Get the number of bytes to transfer.
- LES BX,xmsgpmemAdr[BP] ; Get the memory address.
- MOV DX,xmsgpHdl[BP] ; Get the XMS handle.
- MOV [XMSmainPUT.DestHandle],DX ; Set it in the move structures.
- MOV [XMSwordPUT.DestHandle],DX ;
- MOV [XMSwordGET.SrcHandle],DX ;
-
- XOR DX,DX ;
- MOV DI,xmsgpblk[BP] ; Get the block number.
- SHR DI,1 ; Form the 32 bit XMS address in
- RCR DX,1 ; DI:DX.
- SHR DI,1 ;
- RCR DX,1 ;
- ADD DX,xmsgpblkAdr[BP] ;
-
- TEST CX,1 ; Check for an odd number of bytes
- JZ MemToXMS02 ; to transfer.
-
- DEC CX ; Decrement to an even number of bytes.
-
- TEST DX,1 ; Check for an odd XMS address.
- JZ MemToXMS01 ;
-
- ; XMS address is odd.
- ; -------------------
- DEC DX ;
- MOV [XMSwordGET.SrcOffset],DX ; Set the XMS address.
- MOV [XMSwordGET.SrcOffsetX],DI ;
- MOV [XMSwordPUT.DestOffset],DX ;
- MOV [XMSwordPUT.DestOffsetX],DI ;
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSwordGET ; Set address of the move structure.
-
- PUSH BX ;
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- POP BX ;
- DEC AX ; Check for errors.
- JNZ MemToXMS03 ; Error out if error.
-
- MOV AH,ES:[BX] ; Get the odd memory byte.
-
- MOV [XMSwordByte+1],AH ; Put it in the moved word.
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSwordPUT ; Set address of the move structure.
-
- PUSH BX ;
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- POP BX ;
- DEC AX ; Check for errors.
- JNZ MemToXMS03 ; Error out if error.
-
- INC BX ; Reset the memory address.
- ADD DX,2 ; And the XMS address.
-
- JMP MemToXMS02 ; Move the block.
-
- MemToXMS01:
- ; XMS address is even.
- ; --------------------
- ADD DX,CX ;
- MOV [XMSwordGET.SrcOffset],DX ; Set the XMS address.
- MOV [XMSwordPUT.DestOffset],DX ;
- SUB DX,CX ;
- MOV [XMSwordGET.SrcOffsetX],DI ;
- MOV [XMSwordPUT.DestOffsetX],DI ;
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSwordGET ; Set address of the move structure.
-
- PUSH BX ;
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- POP BX ;
- DEC AX ; Check for errors.
- JNZ MemToXMS03 ; Error out if error.
-
- XCHG DI,CX ;
- MOV AL,ES:[BX+DI] ; Get the odd memory byte.
- XCHG DI,CX ;
-
- MOV [XMSwordByte],AL ; Set the moved word.
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSwordPUT ; Set address of the move structure.
-
- PUSH BX ;
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- POP BX ;
- DEC AX ; Check for errors.
- JNZ MemToXMS03 ; Error out if error.
-
- MemToXMS02:
- JCXZ MemToXMS04 ; Avoid a zero byte move.
-
- MOV XMSmainPUT.Length,CX ; Set length for the move.
-
- MOV XMSmainPUT.SrcOffset,BX ; Set Memory address.
- MOV XMSmainPUT.SrcOffsetX,ES ;
-
- MOV XMSmainPUT.DestOffset,DX ; Set XMS address.
- MOV XMSmainPUT.DestOffsetX,DI ;
-
- MOV AH,0BH ; Set the XMS move, function code.
- MOV SI,OFFSET XMSmainPUT ; Set address of the move structure.
-
- CALL DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
- DEC AX ; Check for errors.
- JZ MemToXMS05
-
- MemToXMS03:
- MOV AX,XMSmemError ; Set error code if error.
- JMP MemToXMS05 ;
-
- MemToXMS04:
- XOR AX,AX ;
-
- MemToXMS05:
- POP DS
- POP ES
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
-
- POP BP
- RET ; Exit
-
- endproc MemToXMS
-
-
- SUBTTL Last Page
- PAGE+
-
- pwrlolvl_TEXT ENDS
-
- END
-
-
- xmem.asm --------------------- END --------------------------------------
-
- xmemc.c ---------------------------- START -------------------------
-
- /*
-
- Copyright 1994 Alec Russell, ALL rights reserved
- Permission granted to use as you wish.
-
- Slightly higher level xms calls than xmem.asm
-
- */
-
- #include <stdio.h>
- #include <io.h>
- #include <string.h>
- #include <malloc.h>
-
- #include <xmem.h>
-
- xms_head_t xms_head={0}; // set handle to zero
-
-
- /* ---------------------- alloc_xms() ----------------- February 19,1994 */
- short alloc_xms(unsigned short far *size) // size in 16k blocks
- {
- return(XMS_alloc(0, size));
- }
-
- /* ---------------------- xms_to_mem() ---------------- February 19,1994 */
- short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n)
- {
- unsigned short block, boff;
-
- block=off >> XMSBLOCKSHIFT;
- boff=off - (block << XMSBLOCKSHIFT);
-
- return(XMStoMem(handle, block, boff, n, p));
- }
-
- /* ---------------------- mem_to_xms() ---------------- February 19,1994 */
- short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n)
- {
- unsigned short block, boff;
-
- block=off >> XMSBLOCKSHIFT;
- boff=off - (block << XMSBLOCKSHIFT);
-
- return(MemToXMS(handle, block, boff, n, p));
- }
-
- /* ---------------------- qalloc_xms() -------------------- March 8,1994 */
- xms_node_t *qalloc_xms(unsigned long size)
- {
- xms_node_t *node=NULL;
- xms_node_t *t1;
-
- if ( size <= xms_head.avail )
- {
- // look for existing node
- t1=xms_head.next;
- while ( t1 )
- {
- if ( t1->used == 0 && t1->size >= size )
- {
- t1->off=0;
- t1->used=1;
- node=t1;
- break;
- }
- else
- t1=t1->next;
- }
-
- if ( node == NULL ) // didn't find existing node
- {
- node=malloc(sizeof(xms_node_t));
- if ( node )
- {
- node->off=0;
- node->used=1;
- node->size=size;
- node->next=NULL;
- node->start=xms_head.next_off;
- xms_head.avail-=size;
- xms_head.next_off+=size;
- if ( xms_head.next == NULL )
- {
- xms_head.next=node;
- }
- else
- {
- t1=xms_head.next;
- while ( t1->next )
- t1=t1->next;
- t1->next=node;
- }
- }
- else
- pr2("out of near mem in qalloc_xms");
- }
- }
- else
- pr2("out of xms mem in qalloc size %lu avail %lu", size, xms_head.avail);
-
- return(node);
- }
-
- /* ---------------------- qfree_xms() --------------------- March 8,1994 */
- void qfree_xms(xms_node_t *node)
- {
- xms_node_t *t1;
-
- if ( xms_head.next )
- {
- t1=xms_head.next;
- while ( t1 != node && t1 )
- t1=t1->next;
-
- if ( t1 )
- {
- t1->used=0;
- }
- else
- pr2("ERROR didn't find node qfree");
- }
- else
- {
- pr2("ATTEMPTED to qfree empty list");
- }
- }
-
- /* ---------------------- xms_open() ---------------------- March 8,1994 */
- xms_node_t *xms_open(char *file)
- {
- int i;
- xms_node_t *node=NULL;
- FILE *fp;
- char *buffer;
- unsigned long off;
-
- fp=fopen(file, "rb");
- if ( fp )
- {
- node=qalloc_xms(filelength(fileno(fp)));
- if ( node )
- {
- buffer=malloc(4096);
- if ( buffer )
- {
- off=0l;
- while ( (i=fread(buffer, 1, 4096, fp)) )
- {
- mem_to_xms(xms_head.handle, (char far *)buffer, off+node->start, i);
- off+=i;
- }
-
- free(buffer);
- }
- else
- pr2("out of mem in xms_open 1");
- }
-
- fclose(fp);
- }
- else
- pr2("ERROR opening %s in xms_open", file);
-
- return(node);
- }
-
- /* ---------------------- xms_read() ---------------------- March 8,1994 */
- short xms_read(void far *buffer, unsigned short n, xms_node_t *node)
- {
-
- if ( node->off >= node->size )
- return 0;
-
- if ( n+node->off > node->size )
- n=node->size - node->off;
-
- xms_to_mem(xms_head.handle, buffer, node->start+node->off, n);
- node->off+=n;
-
- return(n);
- }
-
- /* ---------------------- xms_write() ---------------------- March 8,1994 */
- short xms_write(void far *buffer, unsigned short n, xms_node_t *node)
- {
-
- if ( node->off >= node->size )
- return 0;
-
- if ( n+node->off > node->size )
- n=node->size - node->off;
-
- mem_to_xms(xms_head.handle, buffer, node->start+node->off, n);
- node->off+=n;
-
- return(n);
- }
-
-
- /* ---------------------- xms_tell() ---------------------- March 8,1994 */
- long xms_tell(xms_node_t *node)
- {
- return node->off;
- }
-
- /* ---------------------- xms_seek() ---------------------- March 8,1994 */
- short xms_seek(xms_node_t *node, long off, short whence)
- {
- short err=0;
-
- switch ( whence )
- {
- case SEEK_SET:
- if ( off < 0l || off > node->size )
- err=1;
- else
- node->off=off;
- break;
-
- case SEEK_END:
- if ( off > 0l || (node->size + off) < 0l )
- err=1;
- else
- node->off=node->size + off;
- break;
-
- case SEEK_CUR:
- if ( node->off + off < 0l || node->off + off > node->size )
- err=1;
- else
- node->off+=off;
- break;
- }
-
- return(err);
- }
-
- /* ---------------------- xms_close() --------------------- March 8,1994 */
- void xms_close(xms_node_t *node)
- {
- qfree_xms(node);
- }
-
- /* ---------------------- init_xms() ---------------------- March 8,1994 */
- short init_xms(unsigned short min_blocks)
- {
- unsigned short blocks;
-
- blocks=XMSblk_available();
- if ( blocks >= min_blocks )
- {
- memset(&xms_head, 0, sizeof(xms_head_t));
- if ( (xms_head.handle=alloc_xms(&blocks)) )
- {
- pr2("blocks minus by = %u", blocks);
- min_blocks-=blocks;
- xms_head.avail=xms_head.total=(unsigned long)min_blocks*XMSBLOCK;
- blocks=min_blocks;
- }
- else
- blocks=0;
- }
- else
- blocks=0;
-
- return(blocks);
- }
-
- /* ---------------------- deinit_xms() -------------------- March 8,1994 */
- void deinit_xms(void)
- {
- xms_node_t *t1, *t2;
-
- if ( xms_head.handle )
- {
- XMS_dealloc(xms_head.handle);
- if ( xms_head.next )
- {
- t1=xms_head.next;
- t2=t1->next;
- while ( t1 )
- {
- free(t1);
- t1=t2;
- t2=t1->next;
- }
- }
-
- memset(&xms_head, 0, sizeof(xms_head_t));
- }
- }
- /* --------------------------- end of file ------------------------- */
-
- xmemc.c ---------------------------- END -------------------------
-